<template>
  <div class="progress-bar">
    <div class="bg"></div>
    <div class="bar" :style="{ width: progress + '%' }"></div>
    <div class="label">{{ progress.toFixed(0) }}%</div>
  </div>
  <button @click="handleClick">完成</button>
</template>

<script setup lang="ts">
import { ref, onMounted } from "vue";

// 进度条当前比例
const progress = ref(0);
// 动画播放状态
const isPlaying = ref(false);
// 动画完成状态
const isCompleted = ref(false);

// 启动进度条动画效果
const start = () => {
  isPlaying.value = true;
  animateProgress(90, 1000).then(() => {
    // if (!isCompleted.value) {
    // 	animateProgress(100, 500);
    // }
  });
};

const animateProgress = (target: number, duration: number) => {
  return new Promise((reslove, reject) => {
    let start = progress.value;
    const end = target;

    const doAnimation = () => {
      const elapsed = Date.now() - startTime;
      const progressValue = Math.min(elapsed / duration, 1);

      progress.value = start + (end - start) * progressValue;

      if (progressValue === 1) {
        reslove(true);
      } else if (isCompleted.value) {
        reslove(true);
      } else {
        requestAnimationFrame(doAnimation);
      }
    };

    const startTime = Date.now();
    requestAnimationFrame(doAnimation);
  });
};

// 完成
const finish = () => {
  isCompleted.value = true;
  progress.value = 100;
};

const handleClick = () => {
  finish();
};

onMounted(() => {
  start();
});
</script>

<style lang="scss" scoped>
.progress-bar {
  position: relative;
  height: 8px;
  margin: 50px 10px;
  width: 500px;
}
.bg {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: #ccc;
  border-radius: 5px;
}
.bar {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  border-radius: 5px;
  background-color: #409eff;
  transition: width 0.5s;
}
.label {
  position: absolute;
  top: -20px;
  left: calc(100% + 5px);
  color: #333;
  font-size: 12px;
}
</style>
